package com.smartfactory.sail.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smartfactory.sail.config.BizzException;
import com.smartfactory.sail.dto.ItemMaterialInfoDto;
import com.smartfactory.sail.entity.*;
import com.smartfactory.sail.entity.enums.PickingStatus;
import com.smartfactory.sail.mapper.*;
import com.smartfactory.sail.service.*;
import com.smartfactory.sail.utils.DateUtils;
import com.smartfactory.sail.utils.PageUtils;
import com.smartfactory.sail.vo.PageParam;
import com.smartfactory.sail.vo.picking.CommitReq;
import com.smartfactory.sail.vo.picking.PickInfoResp;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 王巨壁
 * @since 2019-08-26
 */
@Service
public class PickingServiceImpl extends ServiceImpl<PickingMapper, Picking> implements IPickingService {

    private ItemMapper itemMapper;
    private ItemMaterialMapper itemMaterialMapper;
    private PickingMapper pickingMapper;
    private OrderMapper orderMapper;
    private PickingRecordMapper pickingRecordMapper;
    private StorageCurrentInfoMapper storageCurrentInfoMapper;
    private IPickingRecordService iPickingRecordService;
    private IPlanService iPlanService;
    private IOrderItemService iOrderItemService;

    public PickingServiceImpl(ItemMapper itemMapper, ItemMaterialMapper itemMaterialMapper, PickingMapper pickingMapper, OrderMapper orderMapper, PickingRecordMapper pickingRecordMapper, StorageCurrentInfoMapper storageCurrentInfoMapper, IPickingRecordService iPickingRecordService, IPlanService iPlanService, IOrderItemService iOrderItemService) {
        this.itemMapper = itemMapper;
        this.itemMaterialMapper = itemMaterialMapper;
        this.pickingMapper = pickingMapper;
        this.orderMapper = orderMapper;
        this.pickingRecordMapper = pickingRecordMapper;
        this.storageCurrentInfoMapper = storageCurrentInfoMapper;
        this.iPickingRecordService = iPickingRecordService;
        this.iPlanService = iPlanService;
        this.iOrderItemService = iOrderItemService;
    }

    @Override
    public boolean saveByOrderItem(List<OrderItem> orderItems) {
        //接收新增的领取信息
        List<Picking> pickings = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            Item item = itemMapper.selectById(orderItem.getItemId());
            List<ItemMaterialInfoDto> materialListByProductId = itemMaterialMapper.getMaterialListByProductId(orderItem.getItemId());
            for (ItemMaterialInfoDto itemMaterialInfoDto : materialListByProductId) {

                Picking picking = new Picking();
                picking.setItemId(item.getId());
                picking.setItemCode(item.getCode());
                picking.setItemName(item.getName());
                picking.setItemSize(orderItem.getSize());
                picking.setMaterialId(itemMaterialInfoDto.getMaterialId());
                picking.setMaterialCode(itemMaterialInfoDto.getCode());
                picking.setMaterialName(itemMaterialInfoDto.getName());
                picking.setOrderId(orderItem.getOrderId());
                picking.setReceivedSize(0);
                picking.setUnclaimedMinSize(itemMaterialInfoDto.getSize());
                if (itemMaterialInfoDto.getPickingRate() != null) {
                    int max = itemMaterialInfoDto.getSize() * (itemMaterialInfoDto.getPickingRate() / 100);
                    if (max < itemMaterialInfoDto.getSize()) {
                        picking.setUnclaimedMaxSize(itemMaterialInfoDto.getSize());
                    } else {
                        picking.setUnclaimedMaxSize(max);
                    }
                } else {
                    picking.setUnclaimedMaxSize(itemMaterialInfoDto.getSize());
                }
                picking.setPickingCount(0);
                picking.setOrderCode(orderMapper.selectById(orderItem.getOrderId()).getOrderCode());
                pickings.add(picking);
            }
            return saveBatch(pickings);
        }
        return false;
    }

    @Override
    public IPage<Picking> listPageByWhere(PageParam pageParam, Map<String, Object> queryParam) {

        //分页信息
        Page<Picking> page = new Page<>();
        PageUtils.createPage(page, pageParam);
        QueryWrapper<Picking> query = new QueryWrapper<>();
        query.allEq(queryParam);
        IPage<Picking> listPageByWhere = pickingMapper.getListPageByWhere(page, query);
        for (Picking record : listPageByWhere.getRecords()) {
            if (record.getStatus().equals(PickingStatus.YLQ)) {
                continue;
            }
            LambdaQueryWrapper<PickingRecord> pickingRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            pickingRecordLambdaQueryWrapper.eq(PickingRecord::getPickingId, record.getId());
            List<PickingRecord> pickingRecords = pickingRecordMapper.selectList(pickingRecordLambdaQueryWrapper);
            boolean flag = false;
            for (PickingRecord pickingRecord : pickingRecords) {
                if (pickingRecord.getStatus().equals(PickingStatus.DLQ)) {
                    flag = true;
                }
            }
            if (flag) {
                record.setStatus(PickingStatus.DLQ);
            } else {
                record.setStatus(PickingStatus.YLQ);
            }
        }
        return listPageByWhere;
    }

    /**
     * 获取领料详情
     *
     * @param
     * @return
     */
    @Override
    public PickInfoResp getPickingInfoByOrderItemId(Long pickingId) {
        Picking byId = getById(pickingId);
        PickInfoResp result = new PickInfoResp();
        result.setReceivedSize(byId.getReceivedSize());
        result.setItemId(byId.getItemId());
        result.setItemName(byId.getItemName());
        result.setItemCode(byId.getItemCode());
        result.setItemSize(byId.getItemSize());
        result.setCreateTime(DateUtils.forMatterLocalDateTime(byId.getCreateTime(), DateUtils.dateFormart));
        result.setHourlyCapacity(itemMapper.selectById(byId.getItemId()).getHourlyCapacity());
        // result.setPickingInfoDtos();
        //  result.setPickingRecords();



        /*List<Picking> pickings = pickingMapper.getListByOrderItemId(orderId,itemId);
        Picking picking = pickings.get(0);

        //设置每个原料的详情
        List<PickingInfoDto> pickingInfoDtos = new ArrayList<>();
        List<Long> pickingIds = new ArrayList<>();
        for (Picking p : pickings) {
            PickingInfoDto pickingInfoDto = new PickingInfoDto();
            pickingInfoDto.setPickingId(p.getId());
            pickingInfoDto.setMaterialCode(p.getMaterialCode());
            pickingInfoDto.setMaterialName(p.getMaterialName());
            pickingInfoDto.setUnclaimedMinSize(p.getUnclaimedMinSize());
            pickingInfoDto.setUnclaimedMaxSize(p.getUnclaimedMaxSize());
            pickingInfoDto.setReceivedSize(p.getReceivedSize());
            pickingInfoDto.setPickingCount(p.getPickingCount());
            ItemMaterial byMaterialAndProduc = itemMaterialMapper.getByMaterialAndProduc(p.getMaterialId(), picking.getItemId());
            pickingInfoDto.setNeedSize(byMaterialAndProduc.getSize());
            pickingInfoDtos.add(pickingInfoDto);
            //查询当前库存信息
            StorageCurrentInfo storage = storageCurrentInfoMapper.getItemSize(p.getMaterialId());
            if (storage == null) {
                pickingInfoDto.setStorageSize(0);
            } else {
                pickingInfoDto.setStorageSize(storage.getSize());
            }

            pickingIds.add(p.getId());
        }
        result.setPickingInfoDtos(pickingInfoDtos);
*/
        //设置明细
        LambdaQueryWrapper<PickingRecord> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
        objectLambdaQueryWrapper.eq(PickingRecord::getPickingId, pickingId);
        List<PickingRecord> pickingRecords = pickingRecordMapper.selectList(objectLambdaQueryWrapper);
        if (pickingRecords == null) {
            pickingRecords = new ArrayList<>();
        }
        result.setPickingRecords(pickingRecords);

        return result;
    }

    @Transactional
    @Override
    public boolean commit(List<CommitReq> commitReqs) throws Exception {

        List<Picking> pickings = new ArrayList<>();
        // List<PickingRecord> pickingRecords = new ArrayList<>();
        for (CommitReq req : commitReqs) {
            Long pickingId = req.getPickingId();
            Picking pick = getById(pickingId);
            //本次领取数量
            Integer thisTimeSize = req.getThisTimeSize();

            //查询当前库存信息
            StorageCurrentInfo storage = storageCurrentInfoMapper.getItemSize(pick.getMaterialId());
            if (storage == null) {
                throw new Exception("没查询到库存信息");
            } else {
                //领取数量不能大于仓库当前绑定数量
                Integer size = storage.getSize();
                if (thisTimeSize > size) {
                    throw new Exception("领取数量不能大于库存数量！");
                }
            }

            //Integer max = pick.getUnclaimedMaxSize();
            Integer receivedSize = pick.getReceivedSize();
            //if (receivedSize + thisTimeSize > max) {
            //   throw new Exception("领取数量不能大于最大领取数量");
            // }
            pick.setPickingCount(pick.getPickingCount() + 1);
            //pick.setUnclaimedMaxSize(pick.getUnclaimedMaxSize() - thisTimeSize);
            //pick.setUnclaimedMinSize(pick.getUnclaimedMinSize() - thisTimeSize);
            //pick.setReceivedSize(pick.getReceivedSize() + thisTimeSize);
            //if (pick.getReceivedSize() + thisTimeSize == pick.getUnclaimedMaxSize()) {
            pick.setStatus(PickingStatus.YLQ);
            //}
            pickings.add(pick);

            //保存领取记录
           /* PickingRecord pickingRecord = new PickingRecord();
            pickingRecord.setMaterialId(pick.getItemId());
            pickingRecord.setMaterialCode(pick.getMaterialCode());
            pickingRecord.setMaterialName(pick.getMaterialName());
            pickingRecord.setPickingId(pick.getId());
            pickingRecord.setDeptId(req.getDeptId());
            pickingRecord.setDeptName(req.getDeptName());
            pickingRecord.setUserId(null);
            pickingRecords.add(pickingRecord);*/
        }
        if (updateBatchById(pickings)) {
            //if (iPickingRecordService.saveBatch(pickingRecords)) {
            //  return true;
            //} else {
            return true;
            //}
        } else {
            throw new Exception("领取失败");
        }
    }

    @Transactional
    @Override
    public boolean commit(Long recordId) throws BizzException {
        PickingRecord record = iPickingRecordService.getById(recordId);
        if (record == null) {
            throw new BizzException("今日没有该原料领料信息");
        }
        Long materialId = record.getMaterialId();
        //扣除原料的库存数  size
        //查询当前库存信息
        StorageCurrentInfo storage = storageCurrentInfoMapper.getItemSize(materialId);
        if (storage == null) {
            throw new BizzException("没查询到库存信息");
        } else {
            //领取数量不能大于仓库当前绑定数量
            Integer size = storage.getSize();
            if (record.getSize() > size) {
                throw new BizzException("领取数量不能大于库存数量！");
            }
        }

        Picking picking = getById(record.getPickingId());
        if (record.getSize() > picking.getUnclaimedMaxSize()) {
            throw new BizzException("领取数量不能大于最大待领取数量");
        }

        picking.setPickingCount(picking.getPickingCount() + 1);
        picking.setUnclaimedMaxSize(picking.getUnclaimedMaxSize() - record.getSize());
        picking.setUnclaimedMinSize(picking.getUnclaimedMinSize() - record.getSize());
        picking.setReceivedSize(picking.getReceivedSize() + record.getSize());
        if (picking.getReceivedSize() + record.getSize() == picking.getUnclaimedMaxSize()) {
            picking.setStatus(PickingStatus.YLQ);
        }
        //修改领料主表
        boolean b = updateById(picking);
        if (b) {
            PickingRecord pickingRecord = new PickingRecord();
            pickingRecord.setId(recordId);
            pickingRecord.setStatus(PickingStatus.YLQ);
            //修改领料明细表
            if (iPickingRecordService.updateById(pickingRecord)) {
                storage.setSize(storage.getSize() - record.getSize());
                //扣除库存数量
                if (storageCurrentInfoMapper.updateById(storage) > 0) {
                    return true;
                }
            }
        }
        throw new BizzException("修改失败");
    }

    /**
     * 创建领料信息   定时任务 ;  处理0点之后  今日需要领料大排班
     */
    @Override
    @Scheduled(cron = "0 5 0 1/1 * ?")
    public void creatPicking() {
        LambdaQueryWrapper<Plan> query = new LambdaQueryWrapper<>();
        query.eq(Plan::getPlanDate, DateUtils.getNowDate());
        //查询出所有当天已排班的计划..
        List<Plan> plans = iPlanService.list(query);
        for (Plan plan : plans) {
            Long itemId = plan.getItemId();
            Long orderId = plan.getOrderId();
            Integer hourlyCapacity = plan.getHourlyCapacity();
            Integer workHours = plan.getWorkHours();
            OrderItem orderItem = iOrderItemService.findByOrderIdAndItemId(itemId, orderId);
            Item item = itemMapper.selectById(orderItem.getItemId());
            if (null == item)
                continue;
            int totalSize = (int) Math.ceil(orderItem.getSize() * (100 + item.getScrapRate()) * 1.0 / 100);
            List<ItemMaterialInfoDto> materialListByProductId = itemMaterialMapper.getMaterialListByProductId(itemId);
            materialListByProductId.forEach(itemMaterialInfoDto -> {
                LambdaQueryWrapper<Picking> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(Picking::getItemId, itemId)
                        .eq(Picking::getOrderId, orderId)
                        .eq(Picking::getMaterialId, itemMaterialInfoDto.getMaterialId());
                Picking picking = pickingMapper.selectOne(queryWrapper);
                if (null == picking) {
                    picking = new Picking();
                    picking.setItemId(itemId);
                    picking.setItemCode(plan.getItemCode());
                    picking.setItemName(plan.getItemName());
                    picking.setItemSize(plan.getItemSize());
                    picking.setMaterialId(itemMaterialInfoDto.getMaterialId());
                    picking.setMaterialCode(itemMaterialInfoDto.getCode());
                    picking.setMaterialName(itemMaterialInfoDto.getName());
                    picking.setOrderId(orderId);
                    picking.setOrderCode(plan.getOrderCode());
                    picking.setReceivedSize(0);
                    picking.setUnclaimedMaxSize(totalSize * itemMaterialInfoDto.getSize());
                    picking.setPickingCount(0);
                    picking.setStatus(PickingStatus.DLQ);

                    save(picking);
                }

                PickingRecord pickingRecord = new PickingRecord();
                pickingRecord.setDeptId(plan.getDeptId());
                pickingRecord.setDeptName(plan.getDeptName());
                pickingRecord.setMaterialCode(picking.getMaterialCode());
                pickingRecord.setMaterialId(picking.getMaterialId());
                pickingRecord.setMaterialName(picking.getMaterialName());
                pickingRecord.setPickingId(picking.getId());
                pickingRecord.setStatus(PickingStatus.DLQ);
                pickingRecord.setSize(workHours * hourlyCapacity * itemMaterialInfoDto.getSize());

                iPickingRecordService.save(pickingRecord);
            });
        }
    }
}
